package com.autonavi.yunda.yunji.core.engine.handler;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapExceptionCode;
import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.autonavi.yunda.yunji.common.utils.VipServerUtil;
import com.autonavi.yunda.yunji.common.utils.http.HttpClient;
import com.autonavi.yunda.yunji.common.utils.http.HttpUtil;
import com.autonavi.yunda.yunji.core.engine.handler.vo.HttpOptionVO;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;

import java.util.Map;

/**
 * @author cizhong.wcs
 * @date 2022/4/14 11:15
 */
@Slf4j
public class HttpHandler {
    static HttpClient httpClient = new HttpClient(30,128,10);

    public static Object httpGet(String url) {
        return http(url, "GET", null, null, null, Map.of());
    }

    public static Object http(String url,
                              String method,
                              Map<String, Object> params,
                              Map<String, Object> body,
                              Map<String, String> headers,
                              Map<String, Object> config) {
        try {
            HttpOptionVO httpOptionVO = JsonUtils.from(JsonUtils.toString(config), HttpOptionVO.class);
            //本地测试使用,本地环境没有vipserver插件
            if (httpOptionVO.isVipServer) {
                url = VipServerUtil.getVipUrl(url);
                log.info("vip url = {}", url);
            }
            HttpClient client = httpClient.newClient(httpOptionVO);
            String contentType = httpOptionVO.contentType;
            String responseBody;
            String paramsString;
            if (Strings.isNotBlank(paramsString = HttpUtil.getParamsString(params))) {
                url += "?" + paramsString;
            }
            switch (method) {
                case "POST":
                    responseBody = client.post(
                            url,
                            parseBodyByContentType(body, contentType),
                            headers,
                            httpOptionVO.contentType
                    ).getBody();
                    break;
                case "PUT":
                    responseBody = client.put(
                            url,
                            parseBodyByContentType(body, contentType),
                            headers,
                            httpOptionVO.contentType
                    ).getBody();
                    break;
                default:
                    responseBody = client.get(url, headers).getBody();
            }
            log.info("http url = {} ,resBody = {} ,params = {} ,config = {}", url, logLimitLength(responseBody, 100), params, config);
            return JsonUtils.from(responseBody, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.info("http url = {}", url);
            throw new AmapException(AmapExceptionCode.COMMON_HTTP_ERROR, "http请求异常:" + e.getMessage(), e);
        }
    }

    private static String logLimitLength(String str, int maxLength) {
        if (maxLength >= 0) {
            int length = str.length();
            if (length > maxLength) {
                return Strings.left(str, maxLength) + " ... [ " + (length - maxLength) + " characters are omitted ]";
            }
        }
        return str;
    }

    public static String parseBodyByContentType(Map<String, Object> params, String contentType) {
        if (MapUtils.isEmpty(params) || params.size() == 0) {
            return null;
        }
        if (Strings.isBlank(contentType)) {
            return JsonUtils.toString(params);
        }
        switch (contentType.toLowerCase()) {
            case "application/json":
                return JsonUtils.toString(params);
            case "application/x-www-form-urlencoded":
                StringBuilder builder = new StringBuilder();
                params.forEach((k, v) -> builder.append(k).append("=").append(v).append("&"));
                return builder.substring(0, builder.length() - 1);
            default:
                return null;
        }
    }
}
